package plug_inregistryenhancements;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import org.eclipse.core.internal.registry.ExtensionPointHandle;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.spi.RegistryContributor;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.internal.ui.JavaUIMessages;
import org.eclipse.jdt.internal.ui.dialogs.OpenTypeSelectionDialog;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.pde.internal.runtime.registry.ConfigurationAttributeAdapter;
import org.eclipse.pde.internal.runtime.registry.ConfigurationElementAdapter;
import org.eclipse.pde.internal.runtime.registry.ExtensionAdapter;
import org.eclipse.pde.internal.runtime.registry.IConfigurationAttribute;
import org.eclipse.pde.internal.runtime.registry.ParentAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.osgi.framework.Bundle;

@SuppressWarnings( { "restriction", "deprecation" })
public class OpenActions extends Action implements IMenuCreator {
	private static final ImageDescriptor OPEN_DESCRIPTOR = Activator
			.getImageDescriptor("icons/open.gif");

	private ParentAdapter parentAdapter;
	private ExtensionPointHandle extensionPointHandle;

	public OpenActions() {
		super("Information...", IAction.AS_DROP_DOWN_MENU);
		setImageDescriptor(OPEN_DESCRIPTOR);
		setMenuCreator(this);
	}

	public void init(IViewPart viewPart) {
		ISelectionProvider selectionProvider = viewPart.getSite()
				.getSelectionProvider();
		selectionProvider
				.addSelectionChangedListener(new ISelectionChangedListener() {
					public void selectionChanged(SelectionChangedEvent event) {
						OpenActions.this.selectionChanged(event.getSelection());
					}
				});
		selectionChanged(null);
	}

	public void selectionChanged(ISelection selection) {
		setEnabled(false);
		extensionPointHandle = null;
		parentAdapter = null;
		if (selection instanceof IStructuredSelection) {
			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
			if (structuredSelection.size() != 1) {
				return;
			}
			Object firstElement = structuredSelection.getFirstElement();
			if (firstElement instanceof ExtensionPointHandle) {
				extensionPointHandle = (ExtensionPointHandle) firstElement;
				setEnabled(true);
			} else if (firstElement instanceof ParentAdapter) {
				parentAdapter = (ParentAdapter) firstElement;
				setEnabled(true);
			}
		}
	}

	@Override
	public void run() {
		Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
		if (extensionPointHandle != null) {
			MessageDialog.openInformation(shell, "Extension Point Information", 
					getInformationForExtensionPointHandle(extensionPointHandle));
		} else if (parentAdapter != null) {
			if (parentAdapter instanceof ExtensionAdapter) {
				MessageDialog.openInformation(shell, "Extension Information", 
						getInformationForExtensionAdapter((ExtensionAdapter) parentAdapter));
			} else if (parentAdapter instanceof ConfigurationElementAdapter) {
				MessageDialog.openInformation(shell, "Extension Element Information", 
						getInformationForConfigurationElementAdapter((ConfigurationElementAdapter) parentAdapter));
			} else if (parentAdapter instanceof ConfigurationAttributeAdapter) {
				MessageDialog.openInformation(shell, "Extension Element Attribute Information", 
						getInformationForConfigurationElementAdapter((ConfigurationAttributeAdapter) parentAdapter));
			} 
		}
	}
	
	private Menu menu;

	public void dispose() {
		if (menu != null) {
			menu.dispose();
		}
	}

	public Menu getMenu(Control parent) {
		if (menu != null) {
			menu.dispose();
		}
		menu = new Menu(parent);
		if (extensionPointHandle != null) {
			addMenuItemsForExtensionPointHandle(menu, extensionPointHandle);
		} else if (parentAdapter != null) {
			if (parentAdapter instanceof ExtensionAdapter) {
				addMenuItemsForExtensionAdapter(menu,
						(ExtensionAdapter) parentAdapter);
			} else if (parentAdapter instanceof ConfigurationElementAdapter) {
				addMenuItemsForConfigurationElementAdapter(menu,
						(ConfigurationElementAdapter) parentAdapter);
			} else if (parentAdapter instanceof ConfigurationAttributeAdapter) {
				addMenuItemsForConfigurationAttributeAdapter(menu,
						(ConfigurationAttributeAdapter) parentAdapter);
			}
		}
		return menu;
	}
	
	private static String getInformationForExtensionPointHandle(ExtensionPointHandle extensionPointHandle) {
		IContributor contributor = extensionPointHandle.getContributor();
		String bundleLocation = null;
		Bundle bundle = getBundle(contributor);
		if (bundle != null) {
			bundleLocation = bundle.getLocation().substring(10);
		}
		return 
		    "Extension-point : " + extensionPointHandle.getUniqueIdentifier() + "\n"
		  + "Label : " + extensionPointHandle.getLabel() + "\n"
		  + "Schema : " + extensionPointHandle.getSchemaReference() + "\n"
		  + "Bundle Name : " + contributor.getName() + "\n"
		  + (bundleLocation == null ? "" : "Bundle Location :\n" + bundleLocation) 
		;
	}
	
	private static String getInformationForExtensionAdapter(ExtensionAdapter extensionAdapter) {
		IExtension extension = (IExtension) extensionAdapter.getObject();
		IContributor contributor = extension.getContributor();
		String bundleLocation = null;
		Bundle bundle = getBundle(contributor);
		if (bundle != null) {
			bundleLocation = bundle.getLocation().substring(10);
		}
		return 
		    "Extends Extension-point : " + extension.getExtensionPointUniqueIdentifier() + "\n"
		  + "Bundle Name : " + contributor.getName() + "\n"
		  + (bundleLocation == null ? "" : "Bundle Location :\n" + bundleLocation) 
		;
	}
	
	private static String getInformationForConfigurationElementAdapter(ConfigurationElementAdapter configurationElementAdapter) {
		IConfigurationElement configurationElement = (IConfigurationElement) configurationElementAdapter
		.getObject();
		IContributor contributor = configurationElement.getContributor();
		String bundleLocation = null;
		Bundle bundle = getBundle(contributor);
		if (bundle != null) {
			bundleLocation = bundle.getLocation().substring(10);
		}
		return 
		    "Element : " + configurationElement.getName() + "\n"
		  + "Bundle Name : " + contributor.getName() + "\n"
		  + (bundleLocation == null ? "" : "Bundle Location :\n" + bundleLocation) 
		;
	}
	
	private static String getInformationForConfigurationElementAdapter(ConfigurationAttributeAdapter configurationAttributeAdapter) {
		IConfigurationAttribute configurationAttribute = (IConfigurationAttribute) configurationAttributeAdapter
		.getObject();
		
		return configurationAttribute.getLabel();
	}

	private static void addMenuItemsForExtensionPointHandle(Menu menu,
			final ExtensionPointHandle extensionPointHandle) {
		IContributor contributor = extensionPointHandle.getContributor();
		final Bundle bundle = getBundle(contributor);
		if (bundle != null) {
			MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
			menuItem.setText("Open plugin.xml");
			// Open plugin.xml and schema editor
			menuItem.addSelectionListener(new SelectionListener() {
				
				public void widgetDefaultSelected(SelectionEvent e) {
					widgetSelected(e);
				}

				public void widgetSelected(SelectionEvent e) {
					try {
						URL url = null;
						try {
							url = FileLocator.toFileURL(bundle.getEntry("META-INF/MANIFEST.MF"));
						} catch (IOException el) {
						}
						url = FileLocator.toFileURL(bundle.getEntry("plugin.xml"));
						if (url != null) {
							IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(),
									new URI(url.toString().replaceAll(" ", "%20")),
									"org.eclipse.pde.ui.manifestEditor",
									true);
						}
					} catch (IOException e1) {
					} catch (PartInitException el) {
					} catch (URISyntaxException el) {
					}
				}
			});
		}
	}

	private static void addMenuItemsForExtensionAdapter(Menu menu,
			ExtensionAdapter extensionAdapter) {
		IExtension extension = (IExtension) extensionAdapter.getObject();
		IContributor contributor = extension.getContributor();
		final Bundle bundle = getBundle(contributor);
		if (bundle != null) {
			MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
			menuItem.setText("Open plugin.xml");
			// Open plugin.xml and schema editor
			menuItem.addSelectionListener(new SelectionListener() {
				
				public void widgetDefaultSelected(SelectionEvent e) {
					widgetSelected(e);
				}

				public void widgetSelected(SelectionEvent e) {
					try {
						URL url = null;
						try {
							url = FileLocator.toFileURL(bundle.getEntry("META-INF/MANIFEST.MF"));
						} catch (IOException el) {
						}
						url = FileLocator.toFileURL(bundle.getEntry("plugin.xml"));
						if (url != null) {
							IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(),
									new URI(url.toString().replaceAll(" ", "%20")),
									"org.eclipse.pde.ui.manifestEditor",
									true);
						}
					} catch (IOException e1) {
					} catch (PartInitException el) {
					} catch (URISyntaxException el) {
					}
				}
			});
		}
	}

	private static void addMenuItemsForConfigurationElementAdapter(Menu menu,
			ConfigurationElementAdapter configurationElementAdapter) {
		IConfigurationElement configurationElement = (IConfigurationElement) configurationElementAdapter.getObject();
		IContributor contributor = configurationElement.getContributor();
		final Bundle bundle = getBundle(contributor);
		if (bundle != null) {
			MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
			menuItem.setText("Open plugin.xml");
			// Open plugin.xml and schema editor
			menuItem.addSelectionListener(new SelectionListener() {
				
				public void widgetDefaultSelected(SelectionEvent e) {
					widgetSelected(e);
				}

				public void widgetSelected(SelectionEvent e) {
					try {
						URL url = null;
						try {
							url = FileLocator.toFileURL(bundle.getEntry("META-INF/MANIFEST.MF"));
						} catch (IOException el) {
						}
						url = FileLocator.toFileURL(bundle.getEntry("plugin.xml"));
						if (url != null) {
							IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(),
									new URI(url.toString().replaceAll(" ", "%20")),
									"org.eclipse.pde.ui.manifestEditor",
									true);
						}
					} catch (IOException e1) {
					} catch (PartInitException el) {
					} catch (URISyntaxException el) {
					}
				}
			});
		}
	}

	private static void addMenuItemsForConfigurationAttributeAdapter(Menu menu,
			ConfigurationAttributeAdapter configurationAttributeAdapter) {
		IConfigurationAttribute configurationAttribute = (IConfigurationAttribute) configurationAttributeAdapter
		.getObject();
		
		String label = configurationAttribute.getLabel();
		if (label == null)
		{
			return;
		}
		String copyString = label;
		int indexOfequals = copyString.indexOf('=');
		if (indexOfequals != -1) {
			copyString = copyString.substring(indexOfequals + 2);
		}
		final String finalCopyString = copyString;
		final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
		
		boolean possibleJavaTypeName = true;
		String[] parts = finalCopyString.split("[.$]");
		for (String part : parts) {
			for (int i = 0; i < part.length(); i++) {
				char ch = part.charAt(i);
				if (i == 0) {
					if (!Character.isJavaIdentifierStart(ch)) {
						possibleJavaTypeName = false;
						break;
					}
				} else {
					if (!Character.isJavaIdentifierPart(ch)) {
						possibleJavaTypeName = false;
						break;
					}
				}
			}
			if (!possibleJavaTypeName) {
				break;
			}
		}

		MenuItem menuItem = null;
		if (possibleJavaTypeName) {
			menuItem = new MenuItem(menu, SWT.PUSH);
			menuItem.setText("Open " + finalCopyString);
			// Open plugin.xml and schema editor
			menuItem.addSelectionListener(new SelectionListener() {
				
				public void widgetDefaultSelected(SelectionEvent e) {
					widgetSelected(e);
				}
	
				public void widgetSelected(SelectionEvent e) {
					// Get Clipboard
					Clipboard clipboard = new Clipboard(shell.getDisplay());
					// Put the paths string into the Clipboard
					clipboard.setContents(new Object[] { finalCopyString },
							new Transfer[] { TextTransfer.getInstance() });
					OpenTypeSelectionDialog dialog = new OpenTypeSelectionDialog(shell, true, PlatformUI.getWorkbench().getProgressService(), null, IJavaSearchConstants.TYPE);
					dialog.setTitle(JavaUIMessages.OpenTypeAction_dialogTitle);
					dialog.setMessage(JavaUIMessages.OpenTypeAction_dialogMessage);
					dialog.setInitialPattern(finalCopyString);
	
					int result= dialog.open();
					if (result != IDialogConstants.OK_ID)
						return;
	
					Object[] types= dialog.getResult();
					if (types != null && types.length > 0) {
						IType type= null;
						for (int i= 0; i < types.length; i++) {
							type= (IType) types[i];
							try {
								JavaUI.openInEditor(type, true, true);
							} catch (CoreException x) {
								ExceptionHandler.handle(x, JavaUIMessages.OpenTypeAction_errorTitle, JavaUIMessages.OpenTypeAction_errorMessage);
							}
						}
					}
				}
			});
		}
		menuItem = new MenuItem(menu, SWT.PUSH);
		menuItem.setText("Copy " + finalCopyString);
		// Open plugin.xml and schema editor
		menuItem.addSelectionListener(new SelectionListener() {
			
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}

			public void widgetSelected(SelectionEvent e) {
				// Get Clipboard
				Clipboard clipboard = new Clipboard(shell.getDisplay());
				// Put the paths string into the Clipboard
				clipboard.setContents(new Object[] { finalCopyString },
						new Transfer[] { TextTransfer.getInstance() });
			}
		});
	}

	public Menu getMenu(Menu parent) {
		return null;
	}

	private static Bundle getBundle(IContributor contributor) {
		if (contributor instanceof RegistryContributor) {
			RegistryContributor registryContributor = (RegistryContributor) contributor;
			String actualId = registryContributor.getActualId();
			Bundle[] bundles = Activator.getDefault().getBundle()
					.getBundleContext().getBundles();

			for (Bundle bundle : bundles) {
				if (actualId.equals(Long.toString(bundle.getBundleId()))) {
					return bundle;
				}
			}
		}
		return null;
	}

}
